package hxgo

import (
	"fmt"
	"net/http"
	"errors"
)

// handler object
type Handler struct {
	StaticHandler  HandlerStaticFunc
	DynamicHandler HandlerDynamicFunc
	ErrorHandler   HandlerErrorFunc
}

// handler error struct
type HandlerError struct {
	Err    error
	Status int
}

// check is invalid, we need all handlers available
func (this *Handler) IsValid() bool {
	if this.StaticHandler == nil || this.DynamicHandler == nil || this.ErrorHandler == nil {
		return false
	}
	return true
}

// define static handler
type HandlerStaticFunc func (w http.ResponseWriter, r *http.Request)bool

// define dynamic handler
type HandlerDynamicFunc func (w http.ResponseWriter, r *http.Request)bool

// define error handler
type HandlerErrorFunc func (w http.ResponseWriter, r *http.Request, e HandlerError)

// implement ServeHTTP method
func (this *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {

	// find static file
	if this.StaticHandler(w, r) {
		return
	}

	// do error handler if panic
	defer func() {
		e := recover()
		if e != nil {
			hE := HandlerError{}
			hE.Err = errors.New(fmt.Sprint(e))
			hE.Status = http.StatusInternalServerError
			this.ErrorHandler(w, r, hE)
		}
	}()

	// do dynamic request
	if !this.DynamicHandler(w, r) {
		// not found dynamic result, do 404 in error handler
		e := HandlerError{}
		e.Err = errors.New("Page Not Found")
		e.Status = http.StatusNotFound
		this.ErrorHandler(w, r, e)
	}

}

// create new http handler
func NewHandler(s HandlerStaticFunc, d HandlerDynamicFunc, e HandlerErrorFunc) (*Handler, bool) {
	h := &Handler{}
	h.StaticHandler = s
	h.DynamicHandler = d
	h.ErrorHandler = e
	return h, h.IsValid()
}

